#ifndef __CHANNEL__H
#define __CHANNEL__H

#include <stdio.h>
#include <stdlib.h>
/* CUDA include */
#include <cuda_runtime_api.h>
/* CULA include */
#include <culapackdevice.h>
#include <culablasdevice.h>

/* macro */
#define SIZE_CH 2
#define FIRSTDEVICE 0
#define DELTA 40
#define MEGA 1048576.0f
#define TRUE 0
#define FALSE -1

/* Structure of the virtual channel between host and device processes */
typedef struct channel {
    
    char ins;
    char estr;
    char frees;
    char throwed;
    int matrix_width;
    int matrix_dim;
    
    /* this part of the channel will be allocated on GPU memory */
    unsigned char* buffer_0, *buffer_1;
    float *matrix, *vector, *gradient_matrix, *gradient_vector;
    float* gaussian_par;
    int* pivot_vector;
    
    cudaEvent_t finish;

} Channel;

/* Checks the features of the device and, eventually, returns the device index */
int getPhysicalDevice (float memory_required);

/* Creates a virtual channel between host process and device process for processing data with dimension widthxheigth */
Channel* createVirtualChannel (int device, int width, int heigth);

/* Initialize the parameters for the Gauss-Newton algorithm */
int initializeVirtualChannel (Channel* ch, float* parameters);

/* Deallocates all the support implementing the virtual channel */
int destroyVirtualChannel (Channel* ch);

/* Submits data into the channel */
int submit (Channel* ch, unsigned char* matrix);

/* Returns up to date results */
int getResult (Channel* ch, float* gaussian_parameters);

#endif
